//! 共享状态并发示例
//!
//! 展示如何在多个线程间安全地共享状态
//!
//! ## 概念说明
//!
//! 在某种程度上，任何编程语言中的通道都类似于单一所有权，因为一旦将一个值传送到通道中，
//! 就无法再使用这个值。共享内存类似于多重所有权：多个线程可以同时访问相同的内存位置。
//!
//! 智能指针`Rc<T>`和`RefCell<T>`是不适合在多线程场景中使用的，理由如下：
//! - `Rc<T>`不是线程安全的，可能导致数据竞争
//! - `RefCell<T>`不是线程安全的，可能导致数据竞争
//!
//! Rust提供了线程安全的智能指针用于在多线程环境中共享状态：
//! - `Arc<T>`：原子引用计数，是`Rc<T>`的线程安全版本
//! - `Mutex<T>`：互斥锁，用于保护数据
//!
//! ## 互斥锁（Mutex）概念
//!
//! 互斥锁（mutex）是"mutual exclusion"的缩写，一次只允许一个线程访问数据。
//! 为了访问互斥锁中的数据，线程必须首先获取锁（lock）来表明它希望访问数据。
//! 锁的作用是作为一个信号，告诉数据正在被另一个线程使用，不能被其他线程访问。
//!
//! ## `Mutex<T>`使用规则
//!
//! 1. 在使用数据之前必须先获取锁
//! 2. 使用完数据后必须释放锁
//!
//! ## 共享状态相关知识点
//!
//! | 知识点 | 说明 |
//! |--------|------|
//! | `Arc<T>` | 原子引用计数，线程安全的`Rc<T>` |
//! | `Mutex<T>` | 互斥锁，保护数据 |
//! | lock() | 获取锁，返回MutexGuard |
//! | 死锁 | 多个锁之间的循环依赖 |

use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;

/// 使用Mutex在多个线程间共享可变数据
///
/// 展示如何使用`Arc<Mutex<T>>`在线程间安全地共享可变数据。
/// `Arc<T>`允许多个线程拥有同一个数据的所有权，
/// `Mutex<T>`确保同一时间只有一个线程可以访问数据。
pub fn mutex_example() {
    // Arc<Mutex<T>>组合允许在多个线程间共享可变数据
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];

    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap();
            *num += 1;
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap();
    }

    println!("Result: {}", *counter.lock().unwrap());
}

/// 展示死锁的可能性
///
/// 死锁发生在一个操作需要锁定两个资源，而两个线程各持有一个锁并等待对方释放锁时。
/// 这个示例演示了死锁的情况，仅用于教学目的。
#[allow(dead_code)]
pub fn deadlock_example() {
    let mutex1 = Arc::new(Mutex::new(1));
    let mutex2 = Arc::new(Mutex::new(2));
    let mutex1_clone = Arc::clone(&mutex1);
    let mutex2_clone = Arc::clone(&mutex2);

    // 注意：这个示例可能会导致死锁，仅用于演示目的
    // 在实际代码中应该避免这样的模式
    let handle1 = thread::spawn(move || {
        let _lock1 = mutex1.lock().unwrap();
        thread::sleep(Duration::from_millis(10));
        let _lock2 = mutex2.lock().unwrap();
        println!("Thread 1 acquired both locks");
    });

    let handle2 = thread::spawn(move || {
        let _lock2 = mutex2_clone.lock().unwrap();
        thread::sleep(Duration::from_millis(10));
        let _lock1 = mutex1_clone.lock().unwrap();
        println!("Thread 2 acquired both locks");
    });

    handle1.join().unwrap();
    handle2.join().unwrap();
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_mutex() {
        mutex_example();
    }

    #[test]
    #[ignore] // 忽略这个测试，因为它可能导致死锁
    fn test_deadlock() {
        deadlock_example();
    }
}
